home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Tools - Objects / MacApp / MacApp 2.0 CD Release / MacApp 2.0 (Many Libraries) / Libraries / UMacApp.TScroller.p < prev    next >
Encoding:
Text File  |  1990-03-27  |  21.2 KB  |  849 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { UMacApp.TScroller.p }
  4. { Copyright © 1987-1990 by Apple Computer Inc.    All rights reserved. }
  5.  
  6. {--------------------------------------------------------------------------------------------------}
  7. {$S MAOpen}
  8.  
  9. PROCEDURE TScroller.IScroller(itsSuperView: TView;
  10.                               itsLocation, itsSize: VPoint;
  11.                               itsHSizeDet, itsVSizeDet: SizeDeterminer;
  12.                               itsHorzMax, itsVertMax: VCoordinate;
  13.                               wantHorzSBar, wantVertSBar: BOOLEAN);
  14.  
  15.     VAR
  16.         scrollLimit:        VPoint;
  17.         itsSuperViewsDocument: TDocument;
  18.  
  19.     BEGIN
  20.     fScrollBars[h] := NIL;
  21.     fScrollBars[v] := NIL;
  22.  
  23.     IF itsSuperView <> NIL THEN
  24.         itsSuperViewsDocument := itsSuperView.fDocument
  25.     ELSE
  26.         itsSuperViewsDocument := NIL;        
  27.  
  28.     IView(itsSuperViewsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet);
  29.  
  30.     fTranslation := gZeroVPt;
  31.     fMaxTranslation := gZeroVPt;
  32.     fSBarOffsets := gZeroVRect;
  33.     fRespondsToFunctionKeys := TRUE;
  34.  
  35.     SetScrollParameters(kStdScrollUnit, kStdScrollUnit, FALSE, FALSE);
  36.  
  37.     scrollLimit.h := itsHorzMax;
  38.     scrollLimit.v := itsVertMax;
  39.     SetScrollLimits(scrollLimit, kDontRedraw);
  40.  
  41.     IF wantHorzSBar THEN
  42.         CreateScrollBar(h);
  43.     IF wantVertSBar THEN
  44.         CreateScrollBar(v);
  45.     IF wantHorzSBar | wantVertSBar THEN
  46.         AdjustScrollBars(kDontInvalidate);
  47.     END;
  48.  
  49. {--------------------------------------------------------------------------------------------------}
  50. {$S MAOpen}
  51.  
  52. PROCEDURE TScroller.IRes(itsDocument: TDocument;
  53.                          itsSuperView: TView;
  54.                          VAR itsParams: Ptr);
  55.  
  56.     VAR
  57.         scrollLimit:        VPoint;
  58.  
  59.     BEGIN
  60.     fScrollBars[h] := NIL;
  61.     fScrollBars[v] := NIL;
  62.  
  63.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  64.  
  65.     WITH ScrollerTemplatePtr(itsParams)^ DO
  66.         BEGIN
  67.         fTranslation := gZeroVPt;
  68.         fRespondsToFunctionKeys := TRUE;
  69.         scrollLimit.h := horzMax;
  70.         scrollLimit.v := vertMax;
  71.         SetScrollLimits(scrollLimit, kDontRedraw);
  72.  
  73.         SetScrollParameters(hScrollUnits, vScrollUnits, hConstrain, vConstrain);
  74.         {$Push} {$H-}
  75.         RectToVRect(sBarOffsets, fSBarOffsets);
  76.         {$Pop}
  77.  
  78.         IF wantHSBar THEN
  79.             CreateTemplateScrollBar(h);
  80.         IF wantVSBar THEN
  81.             CreateTemplateScrollBar(v);
  82.         IF wantHSBar | wantVSBar THEN
  83.             AdjustScrollBars(kDontInvalidate);
  84.         END;
  85.  
  86.     OffsetPtr(itsParams, SIZEOF(ScrollerTemplate));
  87.     END;
  88.  
  89. {--------------------------------------------------------------------------------------------------}
  90. {$S MAWriteRes}
  91.  
  92. PROCEDURE TScroller.WRes(theResource: ViewRsrcHndl;
  93.                          VAR itsParams: Ptr); OVERRIDE;
  94.  
  95.     VAR
  96.         scPtr:                ScrollerTemplatePtr;
  97.         aVRect:             VRect;
  98.  
  99.     BEGIN
  100.     INHERITED WRes(theResource, itsParams);
  101.  
  102.     scPtr := ScrollerTemplatePtr(ExpandPtr(theResource, itsParams, SIZEOF(ScrollerTemplate)));
  103.  
  104.     WITH scPtr^ DO
  105.         BEGIN
  106.         wantHSBar := fScrollBars[h] <> NIL;
  107.         wantVSBar := fScrollBars[v] <> NIL;
  108.         vertMax := fScrollLimit.v;
  109.         horzMax := fScrollLimit.h;
  110.         vScrollUnits := fScrollUnit.v;
  111.         hScrollUnits := fScrollUnit.h;
  112.         vConstrain := fConstrain[v];
  113.         hConstrain := fConstrain[h];
  114.         aVRect := fSBarOffsets;
  115.         VRectToRect(aVRect, sBarOffsets);
  116.         END;
  117.     END;
  118.  
  119. {--------------------------------------------------------------------------------------------------}
  120. {$S MAWriteRes}
  121.  
  122. PROCEDURE TScroller.WriteRes(theResource: ViewRsrcHndl;
  123.                              VAR itsParams: Ptr); OVERRIDE;
  124.  
  125.     BEGIN
  126.     gWResSignature := 'scrl'; gWResType := 'TScroller';
  127.     WRes(theResource, itsParams);
  128.     END;
  129.  
  130. {--------------------------------------------------------------------------------------------------}
  131. {$S MAClose}
  132.  
  133. PROCEDURE TScroller.Free; OVERRIDE;
  134.  
  135.     BEGIN
  136.     FreeIfObject(fScrollBars[h]);
  137.     fScrollBars[h] := NIL;
  138.  
  139.     FreeIfObject(fScrollBars[v]);
  140.     fScrollBars[v] := NIL;
  141.  
  142.     INHERITED Free;
  143.     END;
  144.  
  145. {--------------------------------------------------------------------------------------------------}
  146. {$S MAOpen}
  147.  
  148. PROCEDURE TScroller.AddSubView(theSubView: TView); OVERRIDE;
  149.  
  150.     BEGIN
  151.     INHERITED AddSubView(theSubView);
  152.     theSubView.BeInScroller(SELF);
  153.     END;
  154.  
  155. {--------------------------------------------------------------------------------------------------}
  156. {$S MANonRes}
  157.  
  158. PROCEDURE TScroller.AdjustScrollBars(invalidate: BOOLEAN);
  159.  
  160.     VAR
  161.         vhs:                VHSelect;
  162.         aScrollBar:         TScrollBar;
  163.         ortho:                VHSelect;
  164.         loc:                VPoint;
  165.         size:                VPoint;
  166.  
  167.     BEGIN
  168.     FOR vhs := v TO h DO
  169.         BEGIN
  170.         aScrollBar := fScrollBars[vhs];
  171.         IF aScrollBar <> NIL THEN
  172.             BEGIN
  173.             ortho := gOrthogonal[vhs];
  174.             loc := fLocation;
  175.             size := fSize;
  176.             WITH loc DO
  177.                 BEGIN
  178.                 vh[vhs] := vh[vhs] + fSBarOffsets.topLeft.vh[vhs] - 1;
  179.                 vh[ortho] := vh[ortho] + size.vh[ortho];
  180.                 END;
  181.             WITH size, fSBarOffsets DO
  182.                 BEGIN
  183.                 vh[vhs] := vh[vhs] - topLeft.vh[vhs] + botRight.vh[vhs] + 2;
  184.                 vh[ortho] := kSBarSize;
  185.                 END;
  186.  
  187.             WITH size DO
  188.                 aScrollBar.Resize(h, v, invalidate);
  189.             WITH loc DO
  190.                 aScrollBar.Locate(h, v, invalidate);
  191.             END;
  192.         END;
  193.     END;
  194.  
  195. {--------------------------------------------------------------------------------------------------}
  196. {$S MADoCommand}
  197.  
  198. PROCEDURE TScroller.AutoScroll(viewPt: VPoint; VAR delta: VPoint);
  199.  
  200.     VAR
  201.         vhs: VHSelect;
  202.         myExtent: VRect;
  203.  
  204.     FUNCTION ProportionalScroll(diff: VCoordinate; scrollUnit: Point;
  205.                                 maxTranslationchange: VCoordinate; vhs: VHSelect): VCoordinate;
  206.  
  207.         BEGIN
  208.         IF scrollUnit.vh[vhs] <> 0 THEN
  209.             ProportionalScroll := MinMax(scrollUnit.vh[vhs], IntMultiply((diff +
  210.                                                                          (scrollUnit.vh[vhs] DIV
  211.                                                                          2)) DIV
  212.                                                                          scrollUnit.vh[vhs],
  213.                                                                          scrollUnit.vh[vhs]),
  214.                                          maxTranslationchange)
  215.         ELSE
  216.             ProportionalScroll := scrollUnit.vh[vhs];
  217.         END;
  218.  
  219.     BEGIN
  220.     delta := gZeroVPt;
  221.     GetExtent(myExtent);
  222.     FOR vhs := v TO h DO
  223.         IF viewPt.vh[vhs] < myExtent.topLeft.vh[vhs] THEN
  224.             delta.vh[vhs] := - ProportionalScroll(myExtent.topLeft.vh[vhs] - viewPt.vh[vhs],
  225.                                                   fScrollUnit, fTranslation.vh[vhs], vhs)
  226.         ELSE IF viewPt.vh[vhs] > myExtent.botRight.vh[vhs] THEN
  227.             delta.vh[vhs] := ProportionalScroll(viewPt.vh[vhs] - myExtent.botRight.vh[vhs],
  228.                                                 fScrollUnit, fMaxTranslation.vh[vhs] -
  229.                                                 fTranslation.vh[vhs], vhs);
  230.     END;
  231.  
  232. {--------------------------------------------------------------------------------------------------}
  233. {$S MAOpen}
  234.  
  235. PROCEDURE TScroller.CreateTemplateScrollBar(itsDirection: VHSelect);
  236.  
  237.     VAR
  238.         anSScrollBar:        TSScrollBar;
  239.         fi:                 FailInfo;
  240.  
  241.     PROCEDURE HandleFailure(error: OSErr;
  242.                             message: LONGINT);
  243.  
  244.         BEGIN
  245.         Free;
  246.         END;
  247.  
  248.     BEGIN
  249.     CatchFailures(fi, HandleFailure);
  250.  
  251.     anSScrollBar := TSScrollBar(DoCreateViews(fDocument, fSuperView, kScrollBarId, gZeroVPt));
  252.     anSScrollBar.fDirection := itsDirection;            { !!!Unfortunately this is not part of the
  253.                                                          resource }
  254.     anSScrollBar.fShown := IsShown;                        { Only shows if we show }
  255.     anSScrollBar.AttachScroller(SELF);
  256.     Success(fi);
  257.     END;
  258.  
  259. {--------------------------------------------------------------------------------------------------}
  260. {$S MAOpen}
  261.  
  262. PROCEDURE TScroller.CreateScrollBar(itsDirection: VHSelect);
  263.  
  264.     VAR
  265.         anSScrollBar:        TSScrollBar;
  266.         fi:                 FailInfo;
  267.  
  268.     PROCEDURE HandleFailure(error: OSErr;
  269.                             message: LONGINT);
  270.  
  271.         BEGIN
  272.         Free;
  273.         END;
  274.  
  275.     BEGIN
  276.     CatchFailures(fi, HandleFailure);
  277.  
  278.     New(anSScrollBar);
  279.     FailNIL(anSScrollBar);
  280.     anSScrollBar.ISScrollBar(fSuperView, gZeroVPt, gZeroVPt, SizeVariable, SizeVariable,
  281.                              itsDirection, fMaxTranslation.vh[itsDirection], SELF);
  282.     Success(fi);
  283.     END;
  284.  
  285. {--------------------------------------------------------------------------------------------------}
  286. {$S MAScroll}
  287.  
  288. FUNCTION TScroller.DoKeyCommand(ch: CHAR;
  289.                                 aKeyCode: INTEGER;
  290.                                 VAR info: EventInfo): TCommand; OVERRIDE;
  291.  
  292.     PROCEDURE DoPageScroll(partCode: INTEGER);
  293.  
  294.         VAR
  295.             vDelta:             VCoordinate;
  296.  
  297.         BEGIN
  298.         vDelta := ScrollStep(v, partCode);
  299.         IF fScrollBars[v] <> NIL THEN
  300.             fScrollBars[v].DeltaValue(vDelta);
  301.         Update;
  302.         END;
  303.  
  304.     BEGIN
  305.     DoKeyCommand := NIL;
  306.     IF IsViewEnabled & fRespondsToFunctionKeys THEN
  307.         CASE ch OF
  308.             chPageUp:
  309.                 DoPageScroll(inPageUp);
  310.             chPageDown:
  311.                 DoPageScroll(inPageDown);
  312.             chHome:
  313.                 BEGIN
  314.                 ScrollTo(0, 0, kRedraw);
  315.                 Update;
  316.                 END;
  317.             chEnd:
  318.                 BEGIN
  319.                 ScrollTo(fMaxTranslation.h, fMaxTranslation.v, kRedraw);
  320.                 Update;
  321.                 END;
  322.             OTHERWISE
  323.                 DoKeyCommand := INHERITED DoKeyCommand(ch, aKeyCode, info);
  324.         END
  325.     ELSE
  326.         DoKeyCommand := INHERITED DoKeyCommand(ch, aKeyCode, info);
  327.     END;
  328.  
  329. {--------------------------------------------------------------------------------------------------}
  330. {$S MAScroll}
  331.  
  332. PROCEDURE TScroller.DoScroll(delta: VPoint;
  333.                              redraw: BOOLEAN);
  334.  
  335.     VAR
  336.         vhs:                VHSelect;
  337.  
  338.     BEGIN
  339.     FOR vhs := v TO h DO
  340.         IF delta.vh[vhs] < 0 THEN
  341.             delta.vh[vhs] := Max(delta.vh[vhs], - fTranslation.vh[vhs])
  342.         ELSE IF delta.vh[vhs] > 0 THEN
  343.             delta.vh[vhs] := Min(delta.vh[vhs], fMaxTranslation.vh[vhs] - fTranslation.vh[vhs]);
  344.  
  345.     IF NOT EqualVPt(delta, gZeroVPt) THEN
  346.         BEGIN
  347.         {$Push} {$H-}
  348.         AddVPt(delta, fTranslation);
  349.         {$Pop}
  350.  
  351.         InvalidateFocus;                                { …then keep focus accurate. Remember, since
  352.                                                          focus affects clipping, if fMaxTranslation
  353.                                                          has changed then we may be clipped
  354.                                                          differently. Not just translated
  355.                                                          differently. }
  356.  
  357.         IF redraw THEN
  358.             ScrollDraw(delta, kInvalidate);                { !!! In the future the decision will
  359.                                                         be made differently as to how to render }
  360.         END;
  361.     END;
  362.  
  363. {--------------------------------------------------------------------------------------------------}
  364. {$S MAFields}
  365.  
  366. PROCEDURE TScroller.Fields(PROCEDURE DoToField(fieldName: Str255;
  367.                                                fieldAddr: Ptr;
  368.                                                fieldType: INTEGER)); OVERRIDE;
  369.  
  370.     BEGIN
  371.     DoToField('TScroller', NIL, bClass);
  372.     DoToField('fTranslation', @fTranslation, bVPoint);
  373.     DoToField('fScrollLimit', @fScrollLimit, bVPoint);
  374.     DoToField('fMaxTranslation', @fMaxTranslation, bVPoint);
  375.     DoToField('fScrollBars[v]', @fScrollBars[v], bObject);
  376.     DoToField('fScrollBars[h]', @fScrollBars[h], bObject);
  377.     DoToField('fScrollUnit', @fScrollUnit, bPoint);
  378.     DoToField('fSBarOffsets', @fSBarOffsets, bVRect);
  379.     DoToField('fConstrain[h]', @fConstrain[h], bBoolean);
  380.     DoToField('fConstrain[v]', @fConstrain[v], bBoolean);
  381.     DoToField('fRespondsToFunctionKeys', @fRespondsToFunctionKeys, bBoolean);
  382.     INHERITED Fields(DoToField);
  383.     END;
  384.  
  385. {--------------------------------------------------------------------------------------------------}
  386. {$S MAScrollerRes}
  387.  
  388. FUNCTION TScroller.Focus: BOOLEAN;
  389.  
  390.     BEGIN
  391.     Focus := INHERITED Focus;
  392.     gLongOffset := fTranslation;
  393.  
  394.     {$IFC qExperimentalAndUnsupported}
  395.     fFocusRec.LongOffset := fTranslation;
  396.     {$EndC}
  397.     END;
  398.  
  399. {--------------------------------------------------------------------------------------------------}
  400. {$S MAScrollerRes}
  401.  
  402. PROCEDURE TScroller.ForceRedraw; OVERRIDE;
  403.  
  404.     BEGIN
  405.     INHERITED ForceRedraw;
  406.     IF fScrollBars[h] <> NIL THEN
  407.         fScrollBars[h].ForceRedraw;
  408.     IF fScrollBars[v] <> NIL THEN
  409.         fScrollBars[v].ForceRedraw;
  410.     END;
  411.  
  412. {--------------------------------------------------------------------------------------------------}
  413. {$S MAScrollerRes}
  414.  
  415. PROCEDURE TScroller.GetExtent(VAR itsExtent: VRect); OVERRIDE;
  416.  
  417.     BEGIN
  418.     INHERITED GetExtent(itsExtent);
  419.     OffsetVRect(itsExtent, fTranslation.h, fTranslation.v);
  420.     END;
  421.  
  422. {--------------------------------------------------------------------------------------------------}
  423. {$S MAScrollerRes}
  424.  
  425. FUNCTION TScroller.GetScroller(immediateSuperView: BOOLEAN): TScroller;
  426.  
  427.     BEGIN
  428.     GetScroller := SELF;
  429.     END;
  430.  
  431. {--------------------------------------------------------------------------------------------------}
  432. {$S MAScrollerRes}
  433.  
  434. PROCEDURE TScroller.HaveScrollBar(theScrollBar: TSScrollBar;
  435.                                   direction: VHSelect);
  436.  
  437.     BEGIN
  438.     {$IFC qDebug}
  439.     IF (theScrollBar <> NIL) & (theScrollBar.fDirection <> direction) THEN
  440.         ProgramBreak('Scroll bar is wrong direction.');
  441.     {$ENDC}
  442.     fScrollBars[direction] := theScrollBar;
  443.     END;
  444.  
  445. {--------------------------------------------------------------------------------------------------}
  446. {$S MAScrollerRes}
  447.  
  448. PROCEDURE TScroller.LocalToSuper(VAR thePoint: VPoint); OVERRIDE;
  449.  
  450.     VAR
  451.         aVPoint:            VPoint;
  452.  
  453.     BEGIN
  454.     aVPoint := fTranslation;
  455.     SubVPt(aVPoint, thePoint);
  456.     aVPoint := fLocation;
  457.     AddVPt(aVPoint, thePoint);
  458.     END;
  459.  
  460. {--------------------------------------------------------------------------------------------------}
  461. {$S MANonRes}
  462.  
  463. PROCEDURE TScroller.Locate(h, v: VCoordinate;
  464.                            invalidate: BOOLEAN); OVERRIDE;
  465.  
  466.     BEGIN
  467.     INHERITED Locate(h, v, invalidate);
  468.  
  469.     AdjustScrollBars(invalidate);
  470.     END;
  471.  
  472. {--------------------------------------------------------------------------------------------------}
  473. {$S MANonRes}
  474.  
  475. PROCEDURE TScroller.RemoveSubView(theSubView: TView); OVERRIDE;
  476.  
  477.     BEGIN
  478.     theSubView.BeInScroller(NIL);
  479.     INHERITED RemoveSubView(theSubView);
  480.     END;
  481.  
  482. {--------------------------------------------------------------------------------------------------}
  483. {$S MANonRes}
  484.  
  485. PROCEDURE TScroller.Resize(width, height: VCoordinate;
  486.                            invalidate: BOOLEAN); OVERRIDE;
  487.  
  488.     VAR
  489.         vhs:                VHSelect;
  490.         sBarWasVisible:     ARRAY [VHSelect] OF BOOLEAN;
  491.         aVPoint:            VPoint;
  492.  
  493.     BEGIN
  494.  { If the scroll bars are visible, erase them now so that they aren't temporarily
  495.   displayed in the wrong place.}
  496.     FOR vhs := v TO h DO
  497.         IF (fScrollBars[vhs] <> NIL) & fScrollBars[vhs].Focus &
  498.            (fScrollBars[vhs].IsCMgrVisible) THEN
  499.             BEGIN
  500.             sBarWasVisible[vhs] := TRUE;
  501.             IF NOT invalidate THEN
  502.                 HideControl(fScrollBars[vhs].fCmgrControl)
  503.             ELSE
  504.                 fScrollBars[vhs].SetCMgrVisibility(FALSE);
  505.             END
  506.         ELSE
  507.             sBarWasVisible[vhs] := FALSE;
  508.  
  509.     INHERITED Resize(width, height, invalidate);
  510.     AdjustScrollBars(invalidate);
  511.     aVPoint := fScrollLimit;
  512.     SetScrollLimits(aVPoint, kDontRedraw);                {Readjust sbar maximums and fMaxTranslation}
  513.  
  514.     FOR vhs := v TO h DO
  515.         IF sBarWasVisible[vhs] THEN
  516.             fScrollBars[vhs].SetCMgrVisibility(TRUE);
  517.     END;
  518.  
  519. {--------------------------------------------------------------------------------------------------}
  520. {$S MAScroll}
  521.  
  522. PROCEDURE TScroller.RevealRect(rectToReveal: VRect;
  523.                                minToSee: Point;
  524.                                redraw: BOOLEAN); OVERRIDE;
  525.  
  526.     VAR
  527.         myExtent:            VRect;
  528.         vhs:                VHSelect;
  529.         minAmt:             VCoordinate;
  530.         coord:                VCoordinate;
  531.         delta:                VPoint;
  532.  
  533.     BEGIN
  534.     GetExtent(myExtent);
  535.  
  536.     FOR vhs := v TO h DO
  537.         BEGIN
  538.         minAmt := Min(LengthVRect(myExtent, vhs), minToSee.vh[vhs]);
  539.         coord := rectToReveal.topLeft.vh[vhs] + minAmt - myExtent.botRight.vh[vhs];
  540.         IF coord <= 0 THEN
  541.             coord := Min(0, rectToReveal.botRight.vh[vhs] - minAmt - myExtent.topLeft.vh[vhs]);
  542.         delta.vh[vhs] := coord;
  543.         END;
  544.  
  545.     ScrollBy(delta.h, delta.v, redraw);
  546.     END;
  547.  
  548. {--------------------------------------------------------------------------------------------------}
  549. {$S MAScroll}
  550.  
  551. PROCEDURE TScroller.ScrollBy(deltaH, deltaV: VCoordinate;
  552.                              redraw: BOOLEAN);
  553.  
  554.     VAR
  555.         delta:                VPoint;
  556.  
  557.     BEGIN
  558.     IF (deltaH <> 0) | (deltaV <> 0) THEN
  559.         BEGIN
  560.         IF fScrollBars[v] <> NIL THEN
  561.             fScrollBars[v].DeltaValue(deltaV);
  562.         IF fScrollBars[h] <> NIL THEN
  563.             fScrollBars[h].DeltaValue(deltaH);
  564.  
  565.         SetVPt(delta, deltaH, deltaV);
  566.         DoScroll(delta, redraw);
  567.         END;
  568.     END;
  569.  
  570. {--------------------------------------------------------------------------------------------------}
  571. {$S MAScroll}
  572.  
  573. PROCEDURE TScroller.ScrollDraw(delta: VPoint;
  574.                               invalidate: BOOLEAN);
  575.  
  576.     VAR
  577.         visRect:            Rect;
  578.         fi:                 FailInfo;
  579.         {$IFC qExperimentalAndUnsupported}
  580.         oldgEnableDoubleBuffering: BOOLEAN;
  581.         {$EndC}
  582.  
  583.     PROCEDURE HdlScrollDraw(error: OSErr;
  584.                             message: LONGINT);
  585.  
  586.         BEGIN
  587.         {$IFC qExperimentalAndUnsupported}
  588.         gEnableDoubleBuffering := oldgEnableDoubleBuffering;
  589.         {$ELSEC}
  590.         EndUpdate(thePort);                             { Would be a shame to leave the visRgn
  591.                                                          sclunged }
  592.         {$EndC}
  593.         END;
  594.  
  595.     PROCEDURE DoScrollDraw;
  596.  
  597.         VAR
  598.             aPoint: Point;
  599.             aWindow: TWindow;
  600.             theUpdateRgn: RgnHandle;
  601.  
  602.         BEGIN
  603.         IF (ABS(delta.h) > kMaxCoord) | (ABS(delta.v) > kMaxCoord) THEN { too far to scrollrect }
  604.             InvalidRect(visRect)
  605.         ELSE
  606.             BEGIN
  607.             {$IFC qDebug}
  608.             UseTempRgn('TScroller.ScrollDraw');
  609.             {$ENDC}
  610.             
  611.             { If we're in a window then remove the update area from the clipRgn since it contains
  612.             stale bits and it's no use to move them (in fact it's damaging) }
  613.             aWindow := GetWindow;
  614.             if aWindow <> NIL THEN
  615.                 BEGIN
  616.                 theUpdateRgn := WindowPeek(aWindow.fWMgrWindow)^.updateRgn;
  617.                 if not EmptyRgn(theUpdateRgn) THEN
  618.                     begin
  619.  
  620.                     { The update region is in global coords but the clip is in local coords.
  621.                     Offset the region to make it in local coords here and restore it there
  622.                     to save copying it }
  623.                     aPoint := gZeroPt;
  624.                     LocalToGlobal(aPoint);
  625.                     OffsetRgn(theUpdateRgn, -aPoint.h,-aPoint.v);
  626.     
  627.                     DiffRgn(thePort^.clipRgn, theUpdateRgn, gTempRgn);
  628.  
  629.                     OffsetRgn(theUpdateRgn, aPoint.h,aPoint.v);
  630.  
  631.                     SetClip(gTempRgn);
  632.                     END;
  633.                 END;
  634.     
  635.             ScrollRect(visRect, - delta.h, - delta.v, gTempRgn);
  636.             InvalRgn(gTempRgn);
  637.  
  638.             {$IFC qDebug}
  639.             DoneWithTempRgn;
  640.             {$ENDC}
  641.             END;
  642.  
  643.         IF qExperimentalAndUnsupported | NOT invalidate THEN
  644.             Update
  645.         ELSE
  646.             InvalidateFocus;
  647.         END;
  648.  
  649.     BEGIN
  650.     IF Focus THEN
  651.         BEGIN
  652.  
  653.         GetVisibleRect(visRect);
  654.  
  655.         IF gIntenseDebugging THEN
  656.             BEGIN
  657.             WrLblRect('                   visRect', visRect);
  658.             WRITELN;
  659.             WrLblVPt('         gLongOffset', gLongOffset);
  660.             WRITELN;
  661.             END;
  662.  
  663.         IF NOT EmptyRect(visRect) THEN
  664.             BEGIN
  665.             {$IFC qExperimentalAndUnsupported}
  666.             IF gEnableDoubleBuffering & NOT (gPrinting | gDrawingPictScrap) THEN
  667.                 BEGIN
  668.                 oldgEnableDoubleBuffering := gEnableDoubleBuffering;
  669.                 gEnableDoubleBuffering := FALSE;        { so subviews won't attempt to do off screen
  670.                                                          }
  671.                 CatchFailures(fi, HdlScrollDraw);
  672.                 DoOffScreen(DoScrollDraw);
  673.                 Success(fi);
  674.                 gEnableDoubleBuffering := oldgEnableDoubleBuffering;
  675.                 END
  676.             ELSE
  677.                 DoScrollDraw;
  678.             {$ELSEC}
  679.             DoScrollDraw;
  680.             {$EndC}
  681.             END;
  682.         END;
  683.     END;
  684.  
  685. {--------------------------------------------------------------------------------------------------}
  686. {$S MAScroll}
  687.  
  688. FUNCTION TScroller.ScrollRelative(vhs: VHSelect;
  689.                                   sBarValue: VCoordinate): VCoordinate;
  690.  
  691.     VAR
  692.         pixelDelta:         VPoint;
  693.         newValue:            VCoordinate;
  694.  
  695.     BEGIN
  696.     IF fConstrain[vhs] & (sBarValue <> fMaxTranslation.vh[vhs]) THEN
  697.         newValue := (sBarValue + fScrollUnit.vh[vhs] DIV 2) DIV fScrollUnit.vh[vhs] *
  698.                     fScrollUnit.vh[vhs]
  699.     ELSE
  700.         newValue := sBarValue;
  701.  
  702.     pixelDelta := gZeroVPt;
  703.     pixelDelta.vh[vhs] := newValue - fTranslation.vh[vhs];
  704.     DoScroll(pixelDelta, kRedraw);
  705.     ScrollRelative := newValue - sBarValue;
  706.     END;
  707.  
  708. {--------------------------------------------------------------------------------------------------}
  709. {$S MAScroll}
  710.  
  711. FUNCTION TScroller.ScrollStep(vhs: VHSelect;
  712.                               partCode: INTEGER): VCoordinate;
  713.  
  714.     VAR
  715.         scrollUnit:         INTEGER;
  716.         delta:                VCoordinate;
  717.         adjustment:         VCoordinate;
  718.         deltaPt:            VPoint;
  719.  
  720.     BEGIN
  721.     scrollUnit := fScrollUnit.vh[vhs];
  722.     deltaPt := gZeroVPt;
  723.     CASE partCode OF
  724.         inUpButton, inDownButton:
  725.             delta := scrollUnit;
  726.         inPageUp, inPageDown:
  727.             delta := fSize.vh[vhs];
  728.         {$IFC qDebug}
  729.         OTHERWISE
  730.             ProgramBreak(ConcatNumber('TScroller.ScrollStep: bad part code=', partCode));
  731.         {$ENDC}
  732.     END;
  733.  
  734.     IF (partCode = inUpButton) | (partCode = inPageUp) THEN
  735.         delta := - delta;
  736.  
  737.     { Constrain if necessary }
  738.     IF fConstrain[vhs] & (scrollUnit <> 0) THEN
  739.         BEGIN
  740.         adjustment := (Max(0, fTranslation.vh[vhs] + delta)) MOD scrollUnit;
  741.         IF adjustment <> 0 THEN
  742.             IF delta > 0 THEN
  743.                 delta := delta - adjustment
  744.             ELSE
  745.                 delta := delta + (scrollUnit - adjustment)
  746.         END;
  747.     deltaPt.vh[vhs] := delta;
  748.  
  749.     DoScroll(deltaPt, kRedraw);
  750.     ScrollStep := delta;
  751.     END;
  752.  
  753. {--------------------------------------------------------------------------------------------------}
  754. {$S MAScroll}
  755.  
  756. PROCEDURE TScroller.ScrollTo(h, v: VCoordinate;
  757.                              redraw: BOOLEAN);
  758.  
  759.     BEGIN
  760.     ScrollBy(h - fTranslation.h, v - fTranslation.v, redraw);
  761.     END;
  762.  
  763. {--------------------------------------------------------------------------------------------------}
  764. {$S MANonRes}
  765.  
  766. PROCEDURE TScroller.SetScrollLimits(scrollLimit: VPoint;
  767.                                     drawScrollBars: BOOLEAN);
  768.  
  769.     VAR
  770.         maxCoord:            VCoordinate;
  771.         vhs:                VHSelect;
  772.         newTranslation:     VPoint;
  773.  
  774.     BEGIN
  775.     fScrollLimit := scrollLimit;
  776.     newTranslation := fTranslation;
  777.     FOR vhs := v TO h DO
  778.         BEGIN
  779.         maxCoord := Max(0, scrollLimit.vh[vhs] - fSize.vh[vhs]);
  780.         IF maxCoord <> fMaxTranslation.vh[vhs] THEN
  781.             BEGIN
  782.             fMaxTranslation.vh[vhs] := maxCoord;
  783.             IF fScrollBars[vhs] <> NIL THEN
  784.                 fScrollBars[vhs].SetLongMax(maxCoord, drawScrollBars);
  785.  
  786.             IF maxCoord < fTranslation.vh[vhs] THEN
  787.                 newTranslation.vh[vhs] := maxCoord;
  788.             END;
  789.         END;
  790.  
  791.     {$Push}{$H-}
  792.     IF NOT EqualVPt(newTranslation, fTranslation) THEN
  793.     {$Pop}
  794.         ScrollTo(newTranslation.h, newTranslation.v, kRedraw);
  795.     END;
  796.  
  797. {--------------------------------------------------------------------------------------------------}
  798. {$S MANonRes}
  799.  
  800. PROCEDURE TScroller.SetScrollParameters(horzUnits, vertUnits: VCoordinate;
  801.                                         horzConstraint, vertConstraint: BOOLEAN);
  802.  
  803.     BEGIN
  804.     fScrollUnit.h := horzUnits;
  805.     fScrollUnit.v := vertUnits;
  806.     fConstrain[h] := horzConstraint;
  807.     fConstrain[v] := vertConstraint;
  808.     END;
  809.  
  810. {--------------------------------------------------------------------------------------------------}
  811. {$S MANonRes}
  812.  
  813. PROCEDURE TScroller.SubViewChangedSize(theSubView: TView;
  814.                                        delta: VPoint); OVERRIDE;
  815.  
  816.     VAR
  817.         aVPoint:            VPoint;
  818.  
  819.     PROCEDURE DoToSubView(theView: TView);
  820.  
  821.         BEGIN
  822.         WITH aVPoint, theView DO
  823.             BEGIN
  824.             v := Max(v, fLocation.v + fSize.v);
  825.             h := Max(h, fLocation.h + fSize.h);
  826.             END;
  827.         END;
  828.  
  829.     BEGIN
  830.     aVPoint := gZeroVPt;
  831.     EachSubView(DoToSubView);
  832.     SetScrollLimits(aVPoint, kRedraw);
  833.     END;
  834.  
  835. {--------------------------------------------------------------------------------------------------}
  836. {$S MAScrollerRes}
  837.  
  838. PROCEDURE TScroller.SuperToLocal(VAR thePoint: VPoint); OVERRIDE;
  839.  
  840.     VAR
  841.         aVPoint:            VPoint;
  842.  
  843.     BEGIN
  844.     aVPoint := fLocation;
  845.     SubVPt(aVPoint, thePoint);
  846.     aVPoint := fTranslation;
  847.     AddVPt(aVPoint, thePoint);
  848.     END;
  849.